home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 3_0 / RAMSTART / RS(COPY).C < prev    next >
Text File  |  1988-01-13  |  18KB  |  765 lines

  1. /*
  2. RS(Copy).c
  3.  
  4. P/O RamStart.c
  5.  
  6. */
  7.  
  8. #include <MemoryMgr.h>
  9. #include <ResourceMgr.h>
  10. #include <HFS.h>
  11. #include <OSUtil.h>
  12. #include <SegmentLdr.h>
  13. #include <setjmp.h>
  14. #include "RS.h"
  15.  
  16. extern jmp_buf    env;
  17.  
  18.  
  19. /* Defined here */
  20.  
  21. /*-- length of a file name */
  22. #define NameMax 64
  23.  
  24. typedef struct {                                /* Enough data about each file to recreate it. */
  25.     short        refNum, rRefNum;
  26.     long        lgLen, rLgLen;
  27.     char        fndrInfo[16];
  28.     long        crDat, modDat;
  29.     char        dontClose, rDontClose;            /* It is a bad thing to close us or the System. */
  30.     char         name[NameMax];
  31. } FileList;
  32.  
  33. #define HFS_System (FSFCBLen >= 0) /* Bill */
  34. #define mfsSigWord 0xd2d7
  35. #define hfsSigWord 0x4244
  36.  
  37. char CopyFolder();
  38.  
  39. static ioParam    newIO;                            /* for closing the file from NoRamDisk() */
  40.  
  41.  
  42. /* //  */
  43. /* Called if there is a control to file, to copy the files listed in it to
  44. the RAM disk.  Notice if a system or a finder were copied.  Work in the
  45. default volume.  Several special names are recognized:  "=<appl name>" to
  46. substitute for the Finder on exit, "+─" to copy the files in the same
  47. folder as the control file, and empty or blank lines and lines starting with
  48. an asterisk, "*", which are ignored. */
  49.  
  50. CopyCtrlFile( ctrlFileName, ramDrvNum, exitApplP )
  51. char            *ctrlFileName;
  52. short            ramDrvNum;
  53. char            **exitApplP;
  54. {
  55.     short        mssg;
  56.     jmp_buf        oldEnv;
  57.     fileParam    fpb1;
  58.     ioParam        pb;
  59.     FileList    *fileList, *flp;
  60.     short        nFiles,                            /* number of fileList entries used */
  61.                 avail, opened;                    /* number of FCB slots available and used */
  62.     char        *exitAppl;
  63.     short        i, result;
  64.     char        fName[MAXLINE+1];
  65.     char        hadX = 0;
  66.     char        hadCopyFolder = FALSE;
  67.     char        pathBuf[522];
  68.  
  69.     TestDLOG();
  70.     
  71.     
  72.     /* Create the file list on the heap, 'cause it takes 4.8K. */
  73.     
  74.     exitAppl = NewPtr( NameMax );                /* In case we get an exit appl */
  75.     exitAppl[0] = 0;
  76.     
  77.     if( (avail = FCBSlots() - 5) < 4 )
  78.         error("too few fcbs, avail=^2", (long)avail);
  79.     fileList = (FileList *)NewPtr( (avail+2) * sizeof(FileList) );
  80.     
  81.     
  82.     /* If TestDLOG() finds that something has happened, we need to clean up
  83.        by closing the files in fileList and removing fileList. */
  84.     
  85.     nFiles = opened = 0;                        /* initialize in case of early withdrawal */
  86.     newIO.ioRefNum = 0;
  87.     BlockMove( env, oldEnv, sizeof(jmp_buf) );
  88.     
  89.     if( (mssg = setjmp( env )) ) {
  90.         PBClose( &pb, FALSE );
  91.         CloseFiles( fileList, nFiles );
  92.         DisposPtr( fileList );
  93.         DisposPtr( exitAppl );
  94.         BlockMove( oldEnv, env, sizeof(jmp_buf) );
  95.         longjmp( env, mssg );
  96.     }
  97.     
  98.     
  99.     /* Open the control file data fork. */
  100.     
  101.     Clear( pb );
  102.     pb.ioNamePtr = (StringPtr)ctrlFileName;
  103.     pb.ioMisc = pathBuf;
  104.     if( PBOpen(&pb, FALSE) ) {
  105.         error("\pcan't open control file '^1', ioResult=^2", (long)pb.ioResult, (long)0, ctrlFileName);
  106.         BlockMove( oldEnv, env, sizeof(jmp_buf) );
  107.         return( 0 );
  108.     }
  109.     
  110. /* //  */
  111.     while( TRUE ) {
  112.         TestDLOG();
  113.         
  114.         pb.ioBuffer = &fName[1];
  115.         pb.ioReqCount = MAXLINE;
  116.         pb.ioPosMode = ('\r' << 8) | 0x80;        /* read lines at mark */
  117.         
  118.         if( PBRead(&pb, FALSE) ) {
  119.             if( pb.ioResult != eofErr )
  120.                 error("\pcan't read control file '^1', ioResult=^2", (long)pb.ioResult, (long)0, ctrlFileName);
  121.             else if( pb.ioActCount == 0 )         /* end of file */
  122.                 hadX |= CopyList( fileList, nFiles, ramDrvNum, exitAppl );
  123.             
  124.             break;
  125.         }
  126.         
  127.         fName[0] = pb.ioActCount;                /* length of line */
  128.         if( fName[pb.ioActCount] == '\r' )
  129.             --fName[0];
  130.         
  131. /* //  */
  132.         if( ! fName[0]  ||  fName[1] == ' '  ||  fName[1] == '*' )
  133.             continue;                            /* blank line */
  134.         
  135.         else if( fName[1] == '=' ) {
  136.             if( fName[0] > NameMax )            /* set exit appl */
  137.                 fName[0] = NameMax;
  138.             BlockMove( &fName[2], &exitAppl[1], (exitAppl[0] = fName[0] - 1) );
  139.         }
  140.         
  141.         else if( EqualString(fName, "\p+─", FALSE, TRUE) )
  142.             hadCopyFolder = TRUE;                /* will copy our folder */
  143.         
  144.         else {                                    /* a file name */
  145.             Clear( fpb1 );
  146.             fpb1.ioNamePtr = (StringPtr)fName;
  147.             
  148.             while( PBGetFInfo(&fpb1, FALSE) ) {    /* catch bad names here */
  149.                 ParamText( fName, ctrlFileName, NULL, NULL );
  150.                 if( Alert(alrtBadName, FALSE) == 1 )
  151.                     break;
  152.                 TestDLOG();                        /* maybe the user pushed a disk in? */
  153.             }
  154.             
  155.             if( !fpb1.ioResult ) {
  156.                 opened += myOpenFile( fName, &fpb1, &fileList[nFiles++], &result );
  157.                 
  158.                 if( result )                    /* anything we can _GetFileInfo on should be openable. */
  159.                     error("\pcan't open file, result=^2", (long)result);
  160.                 
  161.                 if( opened >= avail ) {
  162.                     hadX |= CopyList( fileList, nFiles, ramDrvNum, exitAppl );
  163.                     nFiles = opened = 0;
  164.                 }
  165.             }
  166.         }
  167.     }
  168.     
  169.     PBClose( &pb, FALSE );
  170.     DisposPtr( fileList );
  171.     
  172.     if( exitAppl[0] )
  173.         *exitApplP = exitAppl;
  174.     else DisposPtr( exitAppl );
  175.     
  176.     BlockMove( oldEnv, env, sizeof(jmp_buf) );
  177.     
  178.     if( hadCopyFolder )
  179.         hadX |= CopyFolder( ramDrvNum, ctrlFileName, *exitApplP );
  180.     
  181.     return( hadX );
  182. }
  183.  
  184. /* //  */
  185. /* Copy the files in the same folder as this program to the RAM disk.
  186. Don't copy this program or the desktop file.  Notice if a system or a
  187. finder were copied; bit-code the result.  Work in the default volume.
  188.  
  189. Under HFS, we don't have to worry about folders -- in fact, the folder in
  190. the Finder info isn't even set!  Simply copy all the files in the current
  191. "volume" (working directory) to the RAM disk. */
  192.  
  193. char CopyFolder( ramDrvNum, ourName, exitAppl )
  194. short            ramDrvNum;                        /* --> */
  195. char            *ourName;                        /* --> */
  196. char            *exitAppl;                        /* --> */
  197. {
  198.     short        mssg;
  199.     jmp_buf        oldEnv;
  200.     fileParam    fpb;
  201.     HVolumeParam vpb;
  202.     short        ourFolder;
  203.     short        nFiles, avail, opened;
  204.     FileList    *fileList, *flp;
  205.     short        i, result;
  206.     char        fName[MAXLINE];
  207.     long        hadX = 0;
  208.     char        isHFS;
  209.     
  210.     
  211.     TestDLOG();
  212.     
  213.     
  214.     /* Create the file list on the heap, 'cause it takes 4.8K. */
  215.     
  216.     if( (avail = FCBSlots() - 5) < 4 )
  217.         error("too few fcbs, avail=^2", (long)avail);
  218.     fileList = (FileList *)NewPtr( (avail+2) * sizeof(FileList) );
  219.     
  220.     
  221.     /* If TestDLOG() finds that something has happened, we need to clean up
  222.        by closing the files in fileList and removing fileList. */
  223.     
  224.     nFiles = opened = 0;
  225.     BlockMove( env, oldEnv, sizeof(jmp_buf) );
  226.     
  227.     if( (mssg = setjmp( env )) ) {
  228.         CloseFiles( fileList, nFiles );
  229.         DisposPtr( fileList );
  230.         BlockMove( oldEnv, env, sizeof(jmp_buf) );
  231.         longjmp( env, mssg );
  232.     }
  233.     
  234.     
  235.     TestDLOG();
  236.     
  237.     
  238.     /* Find our folder. */
  239.     
  240.     Clear( vpb );
  241.     vpb.ioTrap = -1;                            /* hideous and dumb bug in System 3.1 HFS */
  242.     PBHGetVInfo( &vpb, FALSE );
  243.     
  244.     if( (isHFS = (HFS_System  &&  vpb.ioVSigWord == hfsSigWord)) )
  245.         ourFolder = 0;
  246.     
  247.     else {
  248.         Clear( fpb );
  249.         fpb.ioNamePtr = (StringPtr)ourName;        /* Our name better be 31 chars or less, or it will... */
  250.         if( PBGetFInfo( &fpb, FALSE ) )            /* ...have been truncated here. */
  251.             error( "\pcan't get our file info" );
  252.         
  253.         ourFolder = fpb.ioFlFndrInfo.fdFldr;
  254.     }
  255.     
  256. /* //  */
  257.     /* Open several files at a time and then copy them.  This speeds up
  258.        copying of large numbers of files by reducing the number of times
  259.        the directory blocks must be seeked to (except under HFS, which
  260.        can be woefully inefficient). */
  261.     
  262.     Clear( fpb );
  263.     fpb.ioFDirIndex = 1;
  264.     fpb.ioNamePtr = (StringPtr)fName;
  265.     
  266.     while( !fpb.ioResult ) {
  267.     
  268.         /* Open input files and place them in the list to copy if in our folder
  269.            and not us, until we can't open any more files. */
  270.         
  271.         for( nFiles = opened = 0;  opened < avail;  ++fpb.ioFDirIndex ) {
  272.             TestDLOG();
  273.             
  274.             if( PBGetFInfo(&fpb, FALSE) ) {
  275.                 if( fpb.ioResult != fnfErr )
  276.                     error("\pcan't get file info for folder test for '^1', ioResult=^2", (long)fpb.ioResult, (long)0, fName);
  277.                 break;
  278.             }
  279.             
  280.             if( fName[0] >= NameMax )
  281.                 error("\pfile name '^1' too long (>^2)", (long)NameMax, (long)0, fName); /* shouldn't happen */
  282.             
  283.             if(    (isHFS  ||  ourFolder == fpb.ioFlFndrInfo.fdFldr)
  284.                &&  ! EqualString( CurApName, fName, FALSE, TRUE )
  285.                &&  ! EqualString( ourName, fName, FALSE, TRUE )
  286.                &&  ! EqualString( "\pDeskTop", fName, FALSE, TRUE ) )
  287.             {
  288.                 opened += myOpenFile( fName, &fpb, &fileList[nFiles++], &result );
  289.                 if( result )
  290.                     error("\pCopyFolder() can't open file, result=^2", (long)result);
  291.             }
  292.         }
  293.  
  294.         
  295.         hadX |= CopyList( fileList, nFiles, ramDrvNum, exitAppl );
  296.     }
  297.     
  298.     DisposPtr( fileList );
  299.     BlockMove( oldEnv, env, sizeof(jmp_buf) );
  300.     
  301.     return( hadX );
  302. }
  303.  
  304. /* //  */
  305. /* Open a file, both data and resource forks, and save the data needed to
  306. recreate the file.  If a fork was opened, its refNum will be non-zero.
  307. Return non-zero ioResult if a file can't be opened. */
  308.  
  309. short    myOpenFile( fName, fpbp, flp, resultp )
  310. char            *fName;
  311. fileParam        *fpbp;
  312. FileList        *flp;
  313. short            *resultp;
  314. {
  315.     ioParam        io;
  316.     short        opened = 0;
  317.     
  318.     
  319.     SimpleFName( fName, flp->name );
  320.     ShowFileName( flp->name, ctlIOpenMsg );
  321.     
  322.     
  323.     /* Set up defaults in file list entry. */
  324.     
  325.     flp->refNum = flp->rRefNum = 0;                /* not open */
  326.     flp->lgLen = fpbp->ioFlLgLen;
  327.     flp->rLgLen = fpbp->ioFlRLgLen;
  328.     BlockMove( &fpbp->ioFlFndrInfo, flp->fndrInfo, 16);
  329.     flp->crDat = fpbp->ioFlCrDat;
  330.     flp->modDat = fpbp->ioFlMdDat;
  331.     flp->dontClose = flp->rDontClose = FALSE;
  332.     
  333.  
  334.     /* Set up open pb. */
  335.     
  336.     Clear( io );
  337.     io.ioNamePtr = (StringPtr)fName;
  338.     
  339. /* //  */
  340.     /* Open the data fork if there is one and it's not the System file --
  341.        no, do copy the System file data fork; people complained mightily
  342.        that they couldn't copy the System from the RAM disk.  Lets see how
  343.        they like losing space, instead! */
  344.     
  345.     if( fpbp->ioFlLgLen  /* &&  !EqualString(SysResName, fName, FALSE, TRUE) */ ) {
  346.     
  347.         if( PBOpen(&io, FALSE) ) {
  348.             switch( io.ioResult )
  349.             {
  350.             case opWrErr:
  351.                 flp->dontClose = TRUE;
  352.                 break;
  353.             
  354.             default:
  355.                 *resultp = io.ioResult;
  356.                 return( 0 );
  357.             }
  358.         }
  359.         
  360.         flp->refNum = io.ioRefNum;
  361.         ++opened;
  362.     }
  363.     
  364.     TestDLOG();
  365.  
  366.  
  367.     /* Open the resource fork if there is one. */
  368.     
  369.     if( fpbp->ioFlRLgLen ) {
  370.     
  371.         if( PBOpenRF(&io, FALSE) ) {
  372.             switch( io.ioResult ) {
  373.             case opWrErr:
  374.                 flp->rDontClose = TRUE;
  375.                 break;
  376.             
  377.             default:
  378.                 if( (io.ioRefNum = flp->refNum) )
  379.                     PBClose( &io, FALSE );
  380.                 
  381.                 *resultp = io.ioResult;
  382.                 return( 0 );
  383.             }
  384.         }
  385.         
  386.         flp->rRefNum = io.ioRefNum;
  387.         ++opened;
  388.     }
  389.     
  390.     
  391.     *resultp = 0;
  392.     return( opened );
  393. }
  394.  
  395. /* //  */
  396. /* Copy the open files in the list. */
  397.  
  398. CopyList( fileList, nFiles, ramDrvNum, exitAppl )
  399. FileList        *fileList;
  400. short            nFiles;
  401. short            ramDrvNum;
  402. char            *exitAppl;
  403. {
  404.     short                i;
  405.     long                hadX = 0;
  406.     register FileList    *flp;
  407.     
  408.     
  409.     /* Copy the files in the list to the RAM disk. */
  410.     
  411.     for( i = nFiles, flp = fileList;  i;  --i, ++flp ) {
  412.         ShowFileName( flp->name, ctlICopyMsg );
  413.         
  414.         if( CopyFile( flp, ramDrvNum ) ) {         /* File may not fit. */
  415.             if( EqualString(exitAppl, flp->name, FALSE, TRUE) )
  416.                 hadX |= HadFinder;
  417.             if( EqualString(SysResName, flp->name, FALSE, TRUE) ) {
  418.                 hadX |= HadSystem;
  419.             }
  420.         }
  421.     }
  422.     
  423.     CloseFiles( fileList, nFiles );                /* done with them */
  424.     return( hadX );
  425. }
  426.  
  427. /* //  */
  428. /* Copy a file, both data and resource forks.  Make sure the file fits.
  429. The copy has the same Type and Creator as the original, but its folder is 0
  430. and it is not init'ed.  Work in the default volume and the RAM disk. */
  431.  
  432. CopyFile( flp, ramDrvNum )
  433. FileList        *flp;                            /* --> */
  434. short            ramDrvNum;                        /* --> */
  435. {
  436.     fileParam    newF;
  437.     ioParam        oldIO;
  438.     Ptr            iop;
  439.     char        dontClose;
  440.     char        fits = TRUE;
  441.     
  442.     
  443.     TestDLOG();
  444.     
  445.     
  446.     /* Make pb for SetFileInfo. */
  447.     
  448.     Clear( newF );
  449.     newF.ioNamePtr = (StringPtr)flp->name;
  450.     newF.ioVRefNum = ramDrvNum;
  451.     BlockMove( flp->fndrInfo, &newF.ioFlFndrInfo, 16 );
  452.     newF.ioFlCrDat = flp->crDat;
  453.     newF.ioFlMdDat = flp->modDat;
  454.     
  455.     
  456.     /* Make io pb's for old and new files. */
  457.     
  458.     Clear( oldIO );
  459.     Clear( newIO );
  460.     newIO.ioNamePtr = (StringPtr)flp->name;
  461.     newIO.ioVRefNum = ramDrvNum;
  462.     
  463.     
  464.     /* Create the new file. */
  465.     
  466.     fits = TRUE;
  467.     
  468.     if( PBCreate( &newIO, FALSE ) ) {
  469.         if( newIO.ioResult == dirFulErr )
  470.             ;
  471.         else if( newIO.ioResult == dupFNErr ) {
  472.             if( Alert(alrtAlreadyCopied, FALSE) == alreadyCopiedCancel )
  473.                 longjmp( env, 'SZ' );                /* Never returns. */
  474.             return( FALSE );                    /* avoid second alert */
  475.         }
  476.         else error("\pcan't create new file, ioResult=^2", (long)newIO.ioResult);
  477.         
  478.         fits = FALSE;
  479.     }
  480.     
  481.     TestDLOG();
  482.  
  483. /* //  */
  484.     /* Copy the data fork if there is one. */
  485.     
  486.     if( fits  &&  (oldIO.ioRefNum = flp->refNum) ) {
  487.         if( PBOpen( &newIO, FALSE ) )
  488.             error("\pcan't open new file");
  489.         
  490.         newIO.ioMisc = (Ptr)flp->lgLen;            /* Copy in one extent. */
  491.         
  492.         if( (fits = ! PBSetEOF( &newIO, FALSE )) )
  493.             CopyFork( &oldIO, &newIO );
  494.         
  495.         PBClose( &newIO, FALSE );
  496.         newIO.ioRefNum = 0;
  497.     }
  498.     
  499.     TestDLOG();
  500.     
  501.     
  502.     /* Copy the resource fork. */
  503.     
  504.     if( fits  &&  (oldIO.ioRefNum = flp->rRefNum) ) {
  505.         oldIO.ioMisc = newIO.ioMisc = 0;
  506.  
  507.         if( PBOpenRF( &newIO, FALSE ) )
  508.             error("\pcan't open new resource file");
  509.         
  510.         newIO.ioMisc = (Ptr)flp->rLgLen;        /* Copy in one extent. */
  511.         
  512.         if( (fits = ! PBSetEOF( &newIO, FALSE )) )
  513.             CopyFork( &oldIO, &newIO );
  514.         
  515.         PBClose( &newIO, FALSE );
  516.         newIO.ioRefNum = 0;
  517.     }
  518.     
  519. /* //  */
  520.     if( !fits ) {
  521.         newIO.ioRefNum = 0;
  522.         PBDelete( &newF, FALSE );
  523.         if( Alert(alrtDidntFit, NULL) == didntfitICancel )    /* File name placed in ^0 by ShowFileName(). */
  524.             longjmp( env, 'SZ' );                /* Never returns. */
  525.     }
  526.     else {
  527.         newF.ioFlFndrInfo.fdFlags &= ~0x0100;    /* Not "inited".  Doesn't agree with IM. */
  528.         newF.ioFlFndrInfo.fdLocation.v = newF.ioFlFndrInfo.fdLocation.h = 0;
  529.         
  530.         /* Put system files in "Empty folder".  This didn't work with the v2.6
  531.            Finder, but it works again with later versions. */
  532.         
  533.         {
  534.             short        i;
  535.             static long    types[] = { 'MACS', 'IWRX', 'IWRT', 'LWRT',
  536.                                     'macs', 'acss', 'sysc', 'KEYC',
  537.                                     'keyb', 'cdsc', 'mous', 'soun',
  538.                                     'boot', 0L };
  539.             
  540.             newF.ioFlFndrInfo.fdFldr = 0;
  541.             for( i = 0;  types[i];  ++i ) {
  542.                 if( newF.ioFlFndrInfo.fdCreator == types[i] )
  543.                     newF.ioFlFndrInfo.fdFldr = -1;
  544.             }
  545.         }
  546.         
  547.         if( EqualString(SysResName, flp->name, FALSE, TRUE) )
  548.             CopyBootBlocks( ramDrvNum );
  549.         
  550.         PBSetFInfo( &newF, FALSE );
  551.     }
  552.     
  553.     
  554.     return( fits );
  555. }
  556.  
  557. /* //  */
  558. /* Copy a fork of a file. */
  559.  
  560. CopyFork( old, new )
  561. ioParam            *old, *new;                        /* -->  Changes not used by caller. */
  562. {
  563.     Ptr            buf;
  564.     long        len;                            /* length of buf */
  565.     short        mssg;
  566.     jmp_buf        oldEnv;
  567.     
  568.     
  569.     TestDLOG();
  570.     
  571.     len = (long)new->ioMisc;                    /* length of this fork */
  572.     if( len == 0 )
  573.         return( TRUE );
  574.     
  575.     if( len > 10*1024 )                            /* Make a reasonable size buffer, to limit the time... */
  576.         len = 10*1024;                            /* ...we don't get events. */
  577.     
  578.     if( !(buf = NewPtr(len)) ) {                /* Get a buffer. */
  579.         len = 512;                                /* Try for a small buffer. */
  580.         if( !(buf = NewPtr(len)) )
  581.             error("\pcan't get small buffer");
  582.         return;
  583.     }
  584.     
  585.     
  586.     /* If TestDLOG() finds something has happened, dispose the buffer. */
  587.     
  588.     BlockMove( env, oldEnv, sizeof(jmp_buf) );
  589.     
  590.     if( (mssg = setjmp( env )) ) {
  591.         DisposPtr( buf );
  592.         BlockMove( oldEnv, env, sizeof(jmp_buf) );
  593.         longjmp( env, mssg );
  594.     }
  595.     
  596.     
  597.     old->ioReqCount     = len;
  598.     old->ioBuffer     = new->ioBuffer    = buf;
  599.     old->ioPosOffset = new->ioPosOffset    = 0;
  600.     old->ioPosMode     = new->ioPosMode    = 1;    /* I/O at ioPosOffset. */
  601.     old->ioResult     = new->ioResult    = 0;
  602.     
  603.     
  604.     while( ! (old->ioResult | new->ioResult) ) {
  605.         TestDLOG();
  606.         
  607.         if(    PBRead(old, FALSE) == noErr        /* Stop at error... */
  608.            ||  old->ioResult == eofErr )        /* ...but copy last block. */
  609.         {
  610.             TestDLOG();
  611.             
  612.             new->ioReqCount = old->ioActCount;
  613.             PBWrite( new, FALSE );
  614.         }
  615.     }
  616.     
  617.     
  618.     DisposPtr( buf );
  619.     BlockMove( oldEnv, env, sizeof(jmp_buf) );
  620.     
  621.     if( old->ioResult != eofErr  ||  new->ioResult != noErr )
  622.         error("\ptrouble ^2 ^3 in CopyFork", (long)old->ioResult, (long)new->ioResult);
  623. }
  624.  
  625. /* //  */
  626. /* Close the files in fileList that should be closed. */
  627.  
  628. CloseFiles( flp, nFiles )
  629. register FileList    *flp;
  630. register short        nFiles;
  631. {
  632.     ioParam        io;
  633.     
  634.     
  635.     if( newIO.ioRefNum )                    /* close file we were copying */
  636.         PBClose( &newIO, FALSE );
  637.     
  638.     
  639.     Clear( io );
  640.     
  641.     for(  ;  nFiles;  --nFiles, ++flp ) {
  642.         if( (io.ioRefNum = flp->refNum)  &&  !flp->dontClose ) {
  643.             PBClose( &io, FALSE );
  644.             flp->refNum = 0;
  645.         }
  646.         if( (io.ioRefNum = flp->rRefNum)  &&  !flp->rDontClose ) {
  647.             PBClose( &io, FALSE );
  648.             flp->rRefNum = 0;
  649.         }
  650.     }
  651. }
  652.  
  653. /* //  */
  654. /* Count the number of available FCB slots.  We will open about that many
  655. files (forks), leaving a few for slack and the file to copy with. */
  656.  
  657. short    FCBSlots()
  658. {
  659.     register short        i, fcbLen, avail = 0;
  660.     
  661.     
  662.     fcbLen = (HFS_System) ? FSFCBLen : 30;
  663.     
  664.     for( i = 2;  i < *(short *)FCBSPtr; i += fcbLen )
  665.         if( !*(long *)&FCBSPtr[i] )
  666.             ++avail;
  667.     
  668.     return( avail );
  669. }
  670.  
  671. /* //  */
  672. /* Copy the boot blocks to the RAM disk.  Since Apple refuses to tell us
  673. what the boot blocks contain or whether they may be directly copied, we'll
  674. just wing it and hope for the best. */
  675.  
  676. CopyBootBlocks( ramDrvNum )
  677. short            ramDrvNum;
  678. {
  679.     ioParam        pb;
  680.     char        buf[1024];
  681.     
  682.     
  683.     Clear( pb );
  684.     pb.ioVRefNum = OurDriveNum();
  685.     pb.ioRefNum = GetDriverNum( pb.ioVRefNum );
  686.     pb.ioBuffer = buf;
  687.     pb.ioReqCount = 1024;
  688.     pb.ioPosMode = fsFromStart;
  689.     pb.ioPosOffset = 0;
  690.     if( PBRead(&pb, FALSE)  ||  pb.ioActCount != pb.ioReqCount ) {
  691.         error("\pcan't read boot blocks, ioResult=^2", (long)pb.ioResult);
  692.         return;
  693.     }
  694.     
  695.     pb.ioVRefNum = ramDrvNum;
  696.     pb.ioRefNum = GetDriverNum( pb.ioVRefNum );
  697.     pb.ioPosOffset = 0;
  698.     if( PBWrite(&pb, FALSE)  ||  pb.ioActCount != pb.ioReqCount )
  699.         error("\pcan't write boot blocks, ioResult=^2", (long)pb.ioResult);
  700. }
  701.  
  702. /* //  */
  703. /* Parse off a simple file name from a path name, a pascal string.  Copy the
  704. result to simple, a pascal string. */
  705.  
  706. SimpleFName( path, simple )
  707. char            *path, *simple;
  708. {
  709.     short        i;
  710.     char        *cP;
  711.     
  712.     
  713.     for( i = path[0], cP = &path[i];  i > 0  &&  *cP != ':';  --i, --cP )
  714.         ;
  715.     
  716.     simple[0] = path[0] - i;
  717.     BlockMove( &cP[1], &simple[1], simple[0] );
  718. }
  719.  
  720.  
  721.     short
  722. OurDriveNum()
  723. {
  724.     WDPBRec        pb;
  725.     QElem        *vcbp;
  726.     short        ourDrvNum;
  727.     
  728.     
  729.     Clear( pb );
  730.     PBHGetVol( &pb, FALSE );                    /* Are we on a Sony drive? */
  731.     if( (HFS_System) )
  732.         pb.ioVRefNum = pb.ioWDVRefNum;            /* Replace WD with real volume #. */
  733.     vcbp = VCBQHdr.qHead;
  734.     
  735.     while( TRUE ) {                                /* Convert volume RefNum to a drive number. */
  736.         if( *(short *)&vcbp->qData[78-6] == pb.ioVRefNum ) {
  737.             ourDrvNum = *(short *)&vcbp->qData[72-6];
  738.             break;
  739.         }
  740.         
  741.         if( ! (vcbp = vcbp->qLink) ) {
  742.             error("\pcan't find our drive #");
  743.             ourDrvNum = -1;
  744.         }
  745.     }
  746.     
  747.     return( ourDrvNum );
  748. }
  749.  
  750.  
  751.     short
  752. GetDriverNum( driveNum )
  753. short            driveNum;
  754. {
  755.     DrvQElPtr    dqp;
  756.     
  757.     
  758.     for( dqp = (DrvQElPtr)DrvQHdr.qHead;  dqp;  dqp = (DrvQElPtr)dqp->qLink ) {
  759.         if( dqp->dQDrive == driveNum )
  760.             return( dqp->dQRefNum );
  761.     }
  762.     
  763.     return( 0 );
  764. }
  765.